package com.yyge;

import com.google.common.cache.*;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * LoadingCache - 本地缓存工具
 */
public class LoadingCacheTest {
    public static void main(String[] args) {
        // 移除监听器
        RemovalListener<String, String> removalListener = removal -> {
            System.out.println("移出了key：" + removal.getKey());
            System.out.println("移出了key：" + removal.getCause());
            System.out.println("移出了key：" + removal.getValue());
        };

        // 定义缓存，key-value的形式
        LoadingCache<String, String> caches = CacheBuilder
                .newBuilder()
                // 缓存最大值，超过最大值会移出
                .maximumSize(10)
                // 自上次读取或写入时间开始，10分钟过期
                .expireAfterAccess(10, TimeUnit.MINUTES)
                // 自上次写入时间开始，10分钟过期
                .expireAfterWrite(10, TimeUnit.MINUTES)
                // 基于权重驱逐key
                .maximumWeight(100000)
                .weigher(new Weigher<String, String>() {
                    public int weigh(String k, String v) {
                        // 获取权重
                        return v.getBytes().length;
                    }
                })
                // 设置移出监听器（同步的，高并发可能会阻塞）
                .removalListener(removalListener)
                // 构造获取缓存数据的方法
                .build(
                        new CacheLoader<String, String>() {
                            public String load(String key) {
                                return createValue(key);
                            }
                        });

        // 需要检查异常
        try {
            System.out.println(caches.get("key"));
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        // 不会检查异常
        caches.getUnchecked("key");
        caches.getIfPresent("key");

        // 使用Callable，将call()方法的返回值作为缓存
        try {
            System.out.println(caches.get("ckey", new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return "Callable";
                }
            })); // Callable
            System.out.println(caches.get("ckey")); // Callable
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 直接放缓存
        caches.put("key2", "v2");

        // 将缓存作为ConcurrentMap输出
        System.out.println(caches.asMap());

        // 删除key
        caches.invalidate("key");
        caches.invalidateAll(Arrays.asList("key", "key1"));
        caches.invalidateAll();

        // 清除过期缓存，一般在写入的时候才会清理部分缓存，如果需要，可以手动清除一下
        caches.cleanUp();

    }


    private static String createValue(String key) {
        System.out.println("获取value");
        return "value";
    }
}
